package org.budo.support.freemarker;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;

import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.MapUtil;
import org.budo.support.lang.util.UuidUtil;

import freemarker.cache.StringTemplateLoader;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateHashModel;

/**
 * @author limingwei2
 */
public class FreemarkerUtil {
    public static Template buildTemplate(String templateInput) {
        try {
            @SuppressWarnings("deprecation")
            Configuration configuration = new Configuration(); // 兼容低版本 freemarker

            configuration.setDefaultEncoding("UTF-8");

            StringTemplateLoader templateLoader = new StringTemplateLoader();
            String randomUuid = UuidUtil.randomUuid(); // templateName
            templateLoader.putTemplate(randomUuid, templateInput);

            configuration.setTemplateLoader(templateLoader);

            return configuration.getTemplate(randomUuid);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    @SuppressWarnings("deprecation")
    public static void freemarkerRender(Template freemarkerTemplate, Object dataMap, OutputStream outputStream) {
        try {
            if (null == dataMap) {
                dataMap = MapUtil.stringObjectMap();
            }

            if (dataMap instanceof Map) {
                TemplateHashModel staticModels = BeansWrapper.getDefaultInstance().getStaticModels();
                ((Map) dataMap).put("def", staticModels);
            }

            freemarkerTemplate.process(dataMap, new OutputStreamWriter(outputStream));
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public static Template buildTemplate(InputStream inputStream) {
        return buildTemplate(IoUtil.toString(inputStream));
    }

    public static String freemarkerRender(InputStream templateInputStream, Object dataMap) {
        Template buildTemplate = buildTemplate(templateInputStream);
        return freemarkerRender(buildTemplate, dataMap);
    }

    public static String freemarkerRender(Template freemarkerTemplate, Object dataMap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        freemarkerRender(freemarkerTemplate, dataMap, byteArrayOutputStream);
        return new String(byteArrayOutputStream.toByteArray());
    }

    public static void freemarkerRender(String templateInput, Object dataMap, OutputStream outputStream) {
        Template freemarkerTemplate = buildTemplate(templateInput);
        freemarkerRender(freemarkerTemplate, dataMap, outputStream);
    }

    public static String freemarkerRender(String templateInput, Object dataMap) {
        Template freemarkerTemplate = buildTemplate(templateInput);
        return freemarkerRender(freemarkerTemplate, dataMap);
    }

    public static void freemarkerRender(InputStream templateInputStream, Object dataMap, OutputStream outputStream) {
        Template freemarkerTemplate = buildTemplate(templateInputStream);
        freemarkerRender(freemarkerTemplate, dataMap, outputStream);
    }
}